﻿/*
 * Jonathan
 * Created by: Jonathan Montiverdi
 * Date: 7/23/2012
 * License: http://jonathan.codeplex.com/license
 */
using System;
using System.Collections.ObjectModel;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Input;

using Jonathan.Data;
using Jonathan.DataAccess.MediaWiki;
using Monti.Docking;
using Monti.MVVM;
using Monti.MVVM.Services;

namespace Jonathan.Logic
{
   /// <summary>
   /// Helps upload data to the learnto.seekdeepwithin.com wiki.
   /// </summary>
   public class WikiUploadViewModel : DockItem
   {
      #region Fields
      
      private IMain m_Main;
      private IOptions m_Options;
      private RelayCommand m_CmdAction;
      private readonly ConsoleRedirection m_Redirection;
      private readonly Regex m_RegExDef = new Regex (@"{{Definition\|(.+)\|(.+)}}");
      
      private string m_Log;
      private string m_SaveFile;
      private string m_Password;
      private string m_SelectedAction;
      private string m_PageTitle = string.Empty;
      private string m_Book = string.Empty;
      private string m_Chapter = string.Empty;
      private string m_Verse = "1";
      private string m_Header = string.Empty;
      private string m_Footer = string.Empty;
      private string m_Passage = string.Empty;
      private string m_Content = string.Empty;
      private string m_LastVerse = string.Empty;
      private string m_LastChapter = string.Empty;
      private string m_BreakReplacement = " ";
      private string m_UploadButtonText;
      
      private const string UPLOAD_WIKI = "Upload to Wiki";
      private const string SAVE_TO_FILE = "Save to file";
      private const string UPLOAD_FILE_WIKI = "Upload file to Wiki";
      
      private MediaWikiSite m_Site;
      private bool m_IsLoggedIn;
      private bool m_UploadChapter;
      private bool m_IsInputGridVisible;
      private bool m_IsLoginGridVisible;
      private bool m_IsSaveFileGridVisible;
      private bool m_IsUploadFileGridVisible;
      private bool m_CopyHeaderToFooter;
      private bool m_ReplaceLineBreaks;
      private bool? m_UploadType;
      
      #endregion
      
      #region Setup
      
      /// <summary>
      /// Initializes a new wiki uploader.
      /// </summary>
      public WikiUploadViewModel()
      {
         this.m_UploadType = true;
         this.Title = "Upload to Wiki";
         this.BreakReplacements = new ObservableCollection <string> { " |(space)", "<br />|(html break)" };
         this.Actions = new ObservableCollection <string> { UPLOAD_WIKI, SAVE_TO_FILE, UPLOAD_FILE_WIKI };
         this.SelectedAction = "Upload to Wiki";
         
         this.m_Redirection = new ConsoleRedirection ();
         Console.SetOut (this.m_Redirection);
         this.m_Redirection.LineWritten += this.OnConsoleWriteLine;
         this.Main.Disposing += this.Dispose;
      }
      
      #endregion
      
      #region Properties
      
      /// <summary>
      /// Gets the main application.
      /// </summary>
      public IMain Main { get { return this.m_Main ?? (this.m_Main = ServiceManager.Resolve <IMain> ()); } }
      
      /// <summary>
      /// Gets the application options.
      /// </summary>
      public IOptions Options { get { return this.m_Options ?? (this.m_Options = ServiceManager.Resolve <IOptions> ()); } }
      
      /// <summary>
      /// Gets the command that performs actions.
      /// </summary>
      public ICommand ActionCommand
      {
         get { return this.m_CmdAction ?? (this.m_CmdAction = new RelayCommand (this.DoAction, this.CanDoAction)); }
      }
      
      /// <summary>
      /// Gets the list of break replacements.
      /// </summary>
      public ObservableCollection <string> BreakReplacements { get; private set; }
      
      /// <summary>
      /// Gets the list of break replacements.
      /// </summary>
      public ObservableCollection <string> Actions { get; private set; }
      
      /// <summary>
      /// Gets or Sets if the data input grid is visible or not.
      /// </summary>
      public bool IsInputGridVisible
      {
         get { return this.m_IsInputGridVisible; }
         set
         {
            this.m_IsInputGridVisible = value;
            this.RaisePropertyChanged ("IsInputGridVisible");
         }
      }
   
      /// <summary>
      /// Gets or Sets if the login grid is visible or not.
      /// </summary>
      public bool IsLoginGridVisible
      {
         get { return this.m_IsLoginGridVisible; }
         set
         {
            this.m_IsLoginGridVisible = value;
            this.RaisePropertyChanged ("IsLoginGridVisible");
         }
      }
   
      /// <summary>
      /// Gets or Sets if the save file grid is visible or not.
      /// </summary>
      public bool IsSaveFileGridVisible
      {
         get { return this.m_IsSaveFileGridVisible; }
         set
         {
            this.m_IsSaveFileGridVisible = value;
            this.RaisePropertyChanged ("IsSaveFileGridVisible");
         }
      }
   
      /// <summary>
      /// Gets or Sets if the upload file grid is visible or not.
      /// </summary>
      public bool IsUploadFileGridVisible
      {
         get { return this.m_IsUploadFileGridVisible; }
         set
         {
            this.m_IsUploadFileGridVisible = value;
            this.RaisePropertyChanged ("IsUploadFileGridVisible");
         }
      }
   
      /// <summary>
      /// Gets or Sets if we should automatically upload the chapter.
      /// </summary>
      public bool UploadChapter
      {
         get { return this.m_UploadChapter; }
         set
         {
            this.m_UploadChapter = value;
            this.RaisePropertyChanged ("UploadChapter");
         }
      }
      
      /// <summary>
      /// Gets or Sets if we are uploading a page or not.
      /// </summary>
      public bool IsPage
      {
         get { return this.m_UploadType == null; }
         set
         {
            if (value && this.m_UploadType != null)
            {
               this.m_UploadType = null;
               this.RaisePropertyChanged ("IsPage");
               this.RaisePropertyChanged ("IsExcerpt");
               this.RaisePropertyChanged ("IsChapter");
               this.BuildWikiContent ();
               this.SetTitle ();
            }
         }
      }
      
      /// <summary>
      /// Gets or Sets if we are uploading a excerpt or not.
      /// </summary>
      public bool IsExcerpt
      {
         get { return this.m_UploadType == true; }
         set
         {
            if (value && this.m_UploadType != true)
            {
               this.m_UploadType = true;
               this.RaisePropertyChanged ("IsPage");
               this.RaisePropertyChanged ("IsExcerpt");
               this.RaisePropertyChanged ("IsChapter");
               this.BuildWikiContent ();
               this.SetTitle ();
            }
         }
      }
      
      /// <summary>
      /// Gets or Sets if we are uploading a chapter or not.
      /// </summary>
      public bool IsChapter
      {
         get { return this.m_UploadType == false; }
         set
         {
            if (value && this.m_UploadType != false)
            {
               this.m_UploadType = false;
               this.RaisePropertyChanged ("IsPage");
               this.RaisePropertyChanged ("IsExcerpt");
               this.RaisePropertyChanged ("IsChapter");
               this.BuildWikiContent ();
               this.BuildNavigation();
               this.SetTitle ();
            }
         }
      }

      /// <summary>
      /// Gets or Sets the action we are perfoming.
      /// </summary>
      public string SelectedAction
      {
         get { return this.m_SelectedAction; }
         set
         {
            if (this.m_SelectedAction != value)
            {
               this.m_SelectedAction = value;
               if (this.m_SelectedAction == UPLOAD_WIKI)
               {
                  this.IsInputGridVisible = true;
                  this.IsLoginGridVisible = true;
                  this.IsSaveFileGridVisible = false;
                  this.IsUploadFileGridVisible = false;
                  this.UploadButtonText = "Upload to Wiki";
               }
               else if (this.m_SelectedAction == SAVE_TO_FILE)
               {
                  this.IsInputGridVisible = true;
                  this.IsLoginGridVisible = false;
                  this.IsSaveFileGridVisible = true;
                  this.IsUploadFileGridVisible = false;
                  this.UploadButtonText = "Save to file";
               }
               else if (this.m_SelectedAction == UPLOAD_FILE_WIKI)
               {
                  this.IsLoginGridVisible = true;
                  this.IsInputGridVisible = false;
                  this.IsSaveFileGridVisible = false;
                  this.IsUploadFileGridVisible = true;
               }
               this.RaisePropertyChanged ("SelectedAction");
            }
         }
      }

      /// <summary>
      /// Gets or Sets the file to save to.
      /// </summary>
      public string SaveFile
      {
         get { return this.m_SaveFile; }
         set
         {
            this.m_SaveFile = value;
            this.RaisePropertyChanged ("SaveFile");
         }
      }

      /// <summary>
      /// Gets or Sets the upload button text.
      /// </summary>
      public string UploadButtonText
      {
         get { return this.m_UploadButtonText; }
         set
         {
            this.m_UploadButtonText = value;
            this.RaisePropertyChanged ("UploadButtonText");
         }
      }

      /// <summary>
      /// Gets or Sets the password.
      /// </summary>
      public string Password
      {
         get { return this.m_Password; }
         set
         {
            this.m_Password = value;
            this.RaisePropertyChanged ("Password");
         }
      }

      /// <summary>
      /// Gets or Sets the break replacement.
      /// </summary>
      public string BreakReplacement
      {
         get { return this.m_BreakReplacement; }
         set
         {
            if (value == null) return;
            this.m_BreakReplacement = value.Split ('|')[0];
            this.RaisePropertyChanged ("BreakReplacement");
         }
      }
      
      /// <summary>
      /// Gets or Sets a value indicating whether or not to copy the header to the footer.
      /// </summary>
      public bool CopyHeaderToFooter
      {
         get { return this.m_CopyHeaderToFooter; }
         set
         {
            this.m_CopyHeaderToFooter = value;
            if (this.m_CopyHeaderToFooter)
               this.Footer = this.Header;
            this.RaisePropertyChanged ("CopyHeaderToFooter");
         }
      }
      
      /// <summary>
      /// Gets or Sets a value indicating whether or not to replace line breaks.
      /// </summary>
      public bool ReplaceLineBreaks
      {
         get { return this.m_ReplaceLineBreaks; }
         set
         {
            this.m_ReplaceLineBreaks = value;
            this.RaisePropertyChanged ("ReplaceLineBreaks");
         }
      }

      /// <summary>
      /// Gets or Sets the Excerpt Wiki Page title.
      /// </summary>
      public string PageTitle
      {
         get { return this.m_PageTitle; }
         set
         {
            this.m_PageTitle = value;
            this.RaisePropertyChanged ("PageTitle");
         }
      }

      /// <summary>
      /// Gets or Sets the book title.
      /// </summary>
      public string Book
      {
         get { return this.m_Book; }
         set
         {
            this.m_Book = value;
            this.RaisePropertyChanged ("Book");
            this.SetTitle ();
            this.BuildWikiContent ();
            if (this.IsChapter)
               this.BuildNavigation ();
         }
      }

      /// <summary>
      /// Gets or Sets the chapter.
      /// </summary>
      public string Chapter
      {
         get { return this.m_Chapter; }
         set
         {
            if (this.m_Chapter != value)
            {
               this.m_Chapter = value;
               this.RaisePropertyChanged ("Chapter");
               this.Verse = "1";
               this.SetTitle ();
               this.BuildWikiContent ();
               if (this.IsChapter)
                  this.BuildNavigation ();
            }
         }
      }

      /// <summary>
      /// Gets or Sets the verse.
      /// </summary>
      public string Verse
      {
         get { return this.m_Verse; }
         set
         {
            this.m_Verse = value;
            this.RaisePropertyChanged ("Verse");
            this.SetTitle ();
            this.BuildWikiContent ();
         }
      }

      /// <summary>
      /// Gets or Sets the header.
      /// </summary>
      public string Header
      {
         get { return this.m_Header; }
         set
         {
            this.m_Header = value;
            this.RaisePropertyChanged ("Header");
            if (this.CopyHeaderToFooter)
            {
               this.m_Footer = value;
               this.RaisePropertyChanged ("Footer");
            }
            this.BuildWikiContent ();
         }
      }

      /// <summary>
      /// Gets or Sets the footer.
      /// </summary>
      public string Footer
      {
         get { return this.m_Footer; }
         set
         {
            this.m_Footer = value;
            this.RaisePropertyChanged ("Footer");
            this.BuildWikiContent ();
         }
      }

      /// <summary>
      /// Gets or Sets the passage.
      /// </summary>
      public string Passage
      {
         get { return this.m_Passage; }
         set
         {
            var passage = value;
            if (this.ReplaceLineBreaks)
               passage = this.ReplaceBreaks (passage);
            if (passage.Contains ("*") && string.IsNullOrEmpty (this.Footer))
               this.Footer = "<small>*</small>";
            this.m_Passage = passage.Trim ();
            this.RaisePropertyChanged ("Passage");
            this.BuildWikiContent ();
         }
      }

      /// <summary>
      /// Gets or Sets the content.
      /// </summary>
      public string WikiContent
      {
         get { return this.m_Content; }
         set
         {
            this.m_Content = value;
            this.RaisePropertyChanged ("WikiContent");
         }
      }
      
      /// <summary>
      /// Gets or Sets the log text.
      /// </summary>
      public string Log
      {
         get { return this.m_Log; }
         set
         {
            this.m_Log = value;
            this.RaisePropertyChanged ("Log");
         }
      }
      
      #endregion
      
      #region Methods

      /// <summary>
      /// Occurs when data is written to the console.
      /// </summary>
      /// <param name="sender">TextWriter.</param>
      /// <param name="e">LineEventArgs</param>
      public void OnConsoleWriteLine (object sender, LineEventArgs e)
      {
         this.Log += e.Line;
      }

      /// <summary>
      /// Replaces the breaks in the given text.
      /// </summary>
      /// <param name="text">Text to replace breaks in.</param>
      /// <returns>Text with break replaced.</returns>
      private string ReplaceBreaks (string text)
      {
         return text.Replace ("\r\n", this.BreakReplacement)
            .Replace ("\r", this.BreakReplacement).Replace ("\n", this.BreakReplacement).Replace ("  ", " ");
      }
      
      /// <summary>
      /// Sets the current page title.
      /// </summary>
      private void SetTitle ()
      {
         var title = this.Book;
         if (!string.IsNullOrEmpty (this.Chapter))
            title += ":" + this.Chapter;
         if (!this.IsChapter)
         {
            if (!string.IsNullOrEmpty (this.Verse))
               title += ":" + this.Verse;
         }
         this.PageTitle = title;
      }
      
      /// <summary>
      /// Builds the navigation links for chapters.
      /// </summary>
      private void BuildNavigation ()
      {
         var content = new StringBuilder ();
         content.AppendLine ("{| width=\"100%\"");
         content.AppendLine ("|-");
         var prevChapter = string.Empty;
         var nextChapter = string.Empty;
         int chap;
         if (Int32.TryParse (this.Chapter, out chap))
         {
            if (chap > 1)
               prevChapter = ":" + Convert.ToString (chap - 1);
            nextChapter = ":" + Convert.ToString (chap + 1);
         }
         content.AppendLine (string.Format ("| align=\"left\"| [[{0}{1}]]", this.Book, prevChapter));
         content.AppendLine (string.Format ("| align=\"right\"| [[{0}{1}]]", this.Book, nextChapter));
         content.Append ("|}");
         this.Header = content.ToString ();
      }
      
      /// <summary>
      /// Builds the wiki content.
      /// </summary>
      private void BuildWikiContent ()
      {
         if (this.IsExcerpt)
         {
            var content = new StringBuilder ();
            content.AppendLine ("{{Excerpt");
            content.AppendLine (string.Format ("| book = {0}", this.Book));
            if (!string.IsNullOrEmpty (this.Chapter))
               content.AppendLine (string.Format ("| chapter = {0}", this.Chapter));
            content.AppendLine (string.Format ("| verse = {0}", this.Verse));
            if (this.Passage.Contains ("[[") || this.Passage.Contains ("]]") ||
                this.Passage.Contains ("{{") || this.Passage.Contains ("}}"))
               content.AppendLine (string.Format ("| temppassage = {0}", this.Passage));
            else
               content.AppendLine (string.Format ("| passage = {0}", this.Passage));
            if (!string.IsNullOrEmpty (this.Header) && !this.Header.Contains ("[["))
               content.AppendLine (string.Format ("| header = {0}", this.Header));
            if (!string.IsNullOrEmpty (this.Footer) && !this.Footer.Contains ("[["))
               content.AppendLine (string.Format ("| footer = {0}", this.Footer));
   
            content.AppendLine ("}}");
            if (this.Passage.Contains ("[[") || this.Passage.Contains ("]]") ||
                this.Passage.Contains ("{{") || this.Passage.Contains ("}}"))
            {
               var passage = this.Passage;
               passage = this.m_RegExDef.Replace (passage, delegate (Match match)
                  {
                     return string.Format ("{{{{Definition{{{{!}}}}{0}{{{{!}}}}{1}}}}}",
                                           match.Groups [1].Value, match.Groups [2].Value.Replace ("'", "\\'"));
                  });
               content.AppendLine (string.Format ("{{{{#set:Passage={0}}}}}", passage));
            }
            if (!string.IsNullOrEmpty (this.Header) && this.Header.Contains ("[["))
               content.AppendLine (string.Format ("{{{{#set:Header={0}}}}}", this.Header));
            if (!string.IsNullOrEmpty (this.Footer) && this.Footer.Contains ("[["))
               content.AppendLine (string.Format ("{{{{#set:Footer={0}}}}}", this.Footer));
   
           this.WikiContent = content.ToString ();
         }
         else if (this.IsChapter)
         {
            var content = new StringBuilder ();
            if (!string.IsNullOrEmpty (this.Header))
               content.AppendLine (this.Header);
   
            if (string.IsNullOrEmpty (this.Chapter))
            {
               content.AppendLine ("{{Article");
               content.AppendLine (string.Format ("| article = {0}", this.Book));
               content.AppendLine (string.Format ("| passagelimit = {0}", this.Verse));
               content.AppendLine ("}}");
               content.AppendLine ("[[Category:Article]]");
            }
            else
            {
               content.AppendLine ("{{Chapter");
               content.AppendLine (string.Format ("| book = {0}", this.Book));
               content.AppendLine (string.Format ("| chapter = {0}", this.Chapter));
               content.AppendLine (string.Format ("| passagelimit = {0}", this.Verse));
               content.AppendLine ("}}");
            }
   
            if (!string.IsNullOrEmpty (this.Footer))
               content.AppendLine (this.Footer);
   
            this.WikiContent = content.ToString ();
         }
      }
      
      /// <summary>
      /// Checks to see if an action can be exectued.
      /// </summary>
      /// <param name="parameter">Action to perform.</param>
      private bool CanDoAction (object parameter)
      {
         var param = parameter.ToString ();
         if (param == "VerseMinus")
            return !string.IsNullOrEmpty (this.Verse) && Convert.ToInt32 (this.Verse) > 1;
         if (param == "VersePlus")
            return !string.IsNullOrEmpty (this.Verse);
         if (param == "ChapterMinus")
         {
            int chap;
            return !string.IsNullOrEmpty (this.Chapter) && Int32.TryParse (this.Chapter, out chap) && Convert.ToInt32 (this.Chapter) > 1;
         }
         if (param == "ChapterPlus")
         {
            int chap;
            return !string.IsNullOrEmpty (this.Chapter) && Int32.TryParse (this.Chapter, out chap);
         }
         if (param == "UploadFile")
         {
            if (!this.m_IsLoggedIn)
            {
               return !string.IsNullOrEmpty (this.Options.Configuration.WikiUserName) &&
                      !string.IsNullOrEmpty (this.Password);
            }
            return !string.IsNullOrEmpty (this.SaveFile) && File.Exists (this.SaveFile);
         }
         if (param == "Upload")
         {
            if (!this.m_IsLoggedIn && this.SelectedAction == UPLOAD_WIKI)
            {
               return !string.IsNullOrEmpty (this.Options.Configuration.WikiUserName) &&
                      !string.IsNullOrEmpty (this.Password);
            }
            if (this.SelectedAction == SaveFile && string.IsNullOrEmpty (this.SaveFile))
               return false;
               
            if (this.IsChapter)
            {
               return !string.IsNullOrEmpty (this.Book) &&
                      !string.IsNullOrEmpty (this.Verse);
            }
            if (this.IsExcerpt)
            {
               return !string.IsNullOrEmpty (this.Book) &&
                      !string.IsNullOrEmpty (this.Verse) &&
                      !string.IsNullOrEmpty (this.Passage);
            }
            return !string.IsNullOrEmpty (this.WikiContent) &&
                   !string.IsNullOrEmpty (this.PageTitle);
         }
         if (param == "SaveFile" || param == "OpenFile")
         {
            return true;
         }
         if (param == "ClearLog")
         {
            return !string.IsNullOrEmpty (this.Log);
         }
         if (param == "Clear")
         {
            return !string.IsNullOrEmpty (this.Passage) ||
                   !string.IsNullOrEmpty (this.Header) ||
                   !string.IsNullOrEmpty (this.Footer);
         }
         return false;
      }
      
      /// <summary>
      /// Performs an action.
      /// </summary>
      /// <param name="parameter">Action to perform.</param>
      private void DoAction (object parameter)
      {
         var param = parameter.ToString ();
         if (param == "VerseMinus")
            this.Verse = Convert.ToString (Convert.ToInt32 (this.Verse) - 1);
         else if (param == "VersePlus")
            this.Verse = Convert.ToString (Convert.ToInt32 (this.Verse) + 1);
         else if (param == "ChapterMinus")
            this.Chapter = Convert.ToString (Convert.ToInt32 (this.Chapter) - 1);
         else if (param == "ChapterPlus")
            this.Chapter = Convert.ToString (Convert.ToInt32 (this.Chapter) + 1);
         else if (param == "UploadFile")
         {
            this.UploadWikiFile ();
         }
         else if (param == "Upload")
         {
            if (this.SelectedAction == UPLOAD_WIKI)
               this.UploadToWiki ();
            else if (this.SelectedAction == SAVE_TO_FILE)
               this.SaveToWikiFile ();
         }
         else if (param == "SaveFile")
         {
            var save = ServiceManager.Resolve <ISaveFileService> ();
            save.Title = "File to save Wiki content to";
            save.DefaultExtension = ".txt";
            save.Filter = "Text file (*.txt)|*.txt";
            save.ShowDialog ();
            this.SaveFile = save.FileName;
         }
         else if (param == "OpenFile")
         {
            var open = ServiceManager.Resolve <IOpenFileService> ();
            open.Title = "Open Wiki content file";
            open.AllowMultipleSelection = false;
            open.Filter = "Text file (*.txt)|*.txt";
            open.ShowDialog ();
            this.SaveFile = open.FileName;
         }
         else if (param == "ClearLog")
         {
            this.Log = string.Empty;
         }
         else if (param == "Clear")
         {
            this.Clear ();
         }
      }
      
      /// <summary>
      /// Clears the contents.
      /// </summary>
      private void Clear ()
      {
         this.Passage = string.Empty;
         this.Header = string.Empty;
         this.Footer = string.Empty;
         this.Verse = Convert.ToString (Convert.ToInt32 (this.Verse) + 1);
      }
      
      /// <summary>
      /// Uploads the current content to the wiki.
      /// </summary>
      private void UploadToWiki ()
      {
         if (this.IsExcerpt)
         {
            if (this.m_LastVerse == this.Verse && this.m_LastChapter == this.Chapter)
            {
               var messageBox = ServiceManager.Resolve <IMessageBoxService> ();
               if (!messageBox.ShowYesNo ("The current verse and chapter are the same as the last uploaded verse and chapter, continue?", "Jonathan"))
                  return;
            }

            this.m_LastChapter = this.Chapter;
            this.m_LastVerse = this.Verse;
         }
         this.UploadCurrentData ();
         if (this.UploadChapter && this.IsExcerpt)
         {
            this.UploadChapter = false;
            this.IsChapter = true;
            this.UploadCurrentData ();
            this.IsExcerpt = true;
            this.Clear ();
            if (this.CanDoAction ("ChapterPlus"))
               this.DoAction ("ChapterPlus");
         }
      }
      
      private void UploadCurrentData ()
      {
         // TODO: Add to local database...
         this.Login ();
         var page = this.m_Site.GetPage (this.PageTitle, false);
         page.Content = this.WikiContent;
         page.Save ();
      }
      
      /// <summary>
      /// Saves the current content to a file for uploading later.
      /// </summary>
      private void SaveToWikiFile ()
      {
         using (var writer = new StreamWriter (this.SaveFile, true))
         {
            writer.WriteLine (this.PageTitle);
            writer.WriteLine (this.WikiContent);
         }
         Console.WriteLine (string.Format ("Saved {0} to {1}.", this.PageTitle, this.SaveFile));
      }
      
      /// <summary>
      /// Uploads the content in the given file to the wiki.
      /// </summary>
      private void UploadWikiFile ()
      {
         var newPage = true;
         using (var reader = new StreamReader (this.SaveFile))
         {
            while (reader.Peek () != -1)
            {
               var line = reader.ReadLine ();
               if (string.IsNullOrEmpty (line))
               {
                  newPage = true;
                  if (!string.IsNullOrEmpty (this.PageTitle) && !string.IsNullOrEmpty (this.WikiContent))
                     this.UploadCurrentData ();
                  this.PageTitle = string.Empty;
                  this.WikiContent = string.Empty;
               }
               else if (newPage)
               {
                  this.PageTitle = string.Empty;
                  this.WikiContent = string.Empty;
                  this.PageTitle = line;
                  newPage = false;
               }
               else
               {
                  this.WikiContent += line + Environment.NewLine;
               }
            }
         }
         if (!string.IsNullOrEmpty (this.PageTitle) && !string.IsNullOrEmpty (this.WikiContent))
            this.UploadCurrentData ();
      }
      
      /// <summary>
      /// Logs into the wiki site.
      /// </summary>
      private void Login ()
      {
         if (this.m_IsLoggedIn) return;
         this.m_Site = new MediaWikiSite
            {
               WikiSiteUrl = "http://learnto.seekdeepwithin.com",
               UserName = this.Options.Configuration.WikiUserName,
               UserPassword = this.Password
            };
         this.m_IsLoggedIn = this.m_Site.Login ();
      }
      
      /// <summary>
      /// Releases any resourses and saves the options.
      /// </summary>
      /// <param name="sender">IMain.</param>
      /// <param name="e">EventArgs</param>
      public void Dispose (object sender, EventArgs e)
      {
         this.Main.Disposing -= this.Dispose;
         this.m_Redirection.LineWritten -= this.OnConsoleWriteLine;
      }
      
      #endregion
   }
}
